package com.gdca.sdk.ca.utils;

import android.content.Context;
import android.util.Base64;

import com.gdca.sdk.ca.BuildConfig;
import com.gdca.sdk.ca.Config;
import com.gdca.sdk.ca.SdkManager;
import com.gdca.sdk.ca.listener.RequestCallBack;
import com.gdca.sdk.ca.model.ResponseContent;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.callback.StringCallback;
import com.lzy.okgo.request.BaseRequest;

import org.json.JSONException;
import org.json.JSONObject;

import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.UUID;

import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Response;

/**
 * Created by Dell on 2017/3/15.
 */

public class OkHttpUtils {

    private volatile static OkHttpUtils mInstance;

    private final String TAG = "OkHttpUtils";

    public OkHttpUtils(OkHttpClient okHttpClient) {
    }

    public static OkHttpUtils initClient(OkHttpClient okHttpClient) {
        if (mInstance == null) {
            synchronized (OkHttpUtils.class) {
                if (mInstance == null) {
                    mInstance = new OkHttpUtils(okHttpClient);
                }
            }
        }
        return mInstance;
    }

    public static OkHttpUtils getInstance() {
        return initClient(null);
    }

    /**
     * 带生成signinfo的param
     *
     * @param context
     * @param bussNo
     * @param dataStr
     * @param dataSign   true data参与签名 false data不参与签名
     * @param attachment 附件，字符串格式的
     * @return
     * @throws JSONException
     */
    private String formDataBase64(Context context, String bussNo, String dataStr, boolean dataSign, String attachment) throws JSONException {
        UUID uuid = UUID.randomUUID();
        bussNo = uuid + "";
        JSONObject object = new JSONObject();
        String timestamp = String.valueOf(System.currentTimeMillis());
        object.put("timestamp", timestamp);
        object.put("bussNo", bussNo);
        object.put("app_id", SdkManager.app_id);
        object.put("data", dataStr);
        if (attachment != null && attachment.length() > 0) {
            JSONObject attachmentObj = new JSONObject();
            attachmentObj.put("idPhoto", attachment);
            object.put("attachment", attachmentObj.toString());
        }
        StringBuilder signInfo = new StringBuilder();
        signInfo.append("app_id=").append(SdkManager.app_id);
        if (bussNo != null && bussNo.length() > 0) {
            signInfo.append("&bussNo=").append(bussNo);
        }
        if (dataStr != null && dataStr.length() > 0 && dataSign) {
            signInfo.append("&data=").append(dataStr);
        }
        signInfo.append("&timestamp=").append(timestamp);
        signInfo.append("&app_secret=").append(SdkManager.app_secret);
        object.put("signInfo", EncryptUtils.encryptSHA256ToString(signInfo.toString().getBytes()));
        return object.toString();
    }

    /**
     * 普通post
     *
     * @param context
     * @param needRetry 是否超时弹窗
     * @param url
     * @param bussNo
     * @param data
     * @param callBack
     * @throws JSONException
     */
    public void doPostString(final Context context, boolean needRetry, String url, String bussNo, JSONObject data, final RequestCallBack callBack) throws JSONException {
        doPostString(context, needRetry, url, bussNo, data, null, callBack);
    }

    /**
     * 普通post 默认超时弹窗
     *
     * @param context
     * @param url
     * @param bussNo
     * @param data
     * @param callBack
     * @throws JSONException
     */
    public void doPostString(final Context context, String url, String bussNo, JSONObject data, final RequestCallBack callBack) throws JSONException {
        doPostString(context, true, url, bussNo, data, null, callBack);
    }

    /**
     * 带附件的post
     *
     * @param context
     * @param url
     * @param bussNo
     * @param data
     * @param attachment
     * @param callBack
     * @throws JSONException
     */
    public void doPostString(final Context context, final boolean needRetry, String url, String bussNo, JSONObject data, String attachment, final RequestCallBack callBack) throws JSONException {
        String body;
        if (url.contains("identify")) {
            body = formDataBase64(context, bussNo, data == null ? "" : Base64.encodeToString(data.toString().getBytes(), Base64.NO_WRAP), true, attachment);
        } else {
            body = formDataBase64(context, bussNo, data == null ? "" : Base64.encodeToString(data.toString().getBytes(), Base64.NO_WRAP), true, null);
        }
        doPostString(context, url, body, needRetry, callBack);
    }

    public void doPostString(final Context context, String url, String data, final boolean needRetry, final RequestCallBack callBack) {
        OkGo.post(url)
                .upJson(data)
                .execute(new StringCallback() {
                    @Override
                    public void onAfter(String s, Exception e) {
                        super.onAfter(s, e);
                        if (callBack != null) {
                            callBack.onAfter();
                        }
                    }

                    @Override
                    public void onBefore(BaseRequest request) {
                        super.onBefore(request);
                        if (callBack != null) {
                            callBack.onBefore();
                        }
                    }

                    @Override
                    public void onSuccess(String s, Call call, Response response) {
                        try {
                            if (response.isSuccessful()) {
                                String str = s;
                                sendSuccessResultCallback(call, str, callBack);
                            } else {
                                if (callBack != null) {
                                    String msg = "";
                                    switch (response.code()) {
                                        case 400:
                                            msg = "请求中有语法问题，或不能满足请求";
                                            break;
                                        case 404:
                                            msg = "服务器找不到给定的资源";
                                            break;
                                        case 500:
                                            msg = "服务器不能完成请求";
                                            break;
                                    }
                                    callBack.onFail(response.code(), msg);
                                }
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            if (callBack != null) {
                                callBack.onError(Config.OTHER_ERROR, call, e);
                            }
                        }
                    }

                    @Override
                    public void onError(Call call, Response response, Exception e) {
                        super.onError(call, response, e);
                        e.printStackTrace();
                        if (callBack != null) {
                            if (!NetworkUtil.networkConnected(context)) {
                                Exception exception = new Exception("您的手机没有联网");
                                callBack.onError(Config.NETWORK_TIMEOUT_ERROR, call, exception);
                            } else if (e instanceof SocketException || e instanceof SocketTimeoutException) {
                                callBack.onTimeout(needRetry, e.getMessage());
                            } else {
                                Exception exception;
                                if (StringUtils.isEmpty(e.getMessage()) || !BuildConfig.DEBUG) {
                                    try {
                                        exception = new Exception(response.message());
                                    } catch (Exception e1) {
                                        exception = new Exception("服务器异常");
                                    }
                                } else {
                                    exception = new Exception(e.getMessage());
                                }
                                callBack.onError(response.code(), call, exception);
                            }
                        }
                    }
                });
    }

    private void sendSuccessResultCallback(Call call, String str, final RequestCallBack callback) {
        try {
            JSONObject object = new JSONObject(str);
            final ResponseContent content = new ResponseContent();
            content.setCode(object.optInt("code", 1));
            content.setContent("");
            if (object.opt("content") != null) {
                content.setContent(object.opt("content").toString());
            }
            content.setMessage(object.optString("message", ""));
            if (callback != null) {
                callback.onSuccess(content);
            }
        } catch (JSONException e) {
            e.printStackTrace();
            if (callback != null) {
                callback.onError(Config.OTHER_ERROR, call, e);
            }
        }
    }

}
